﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "LevelNameManager.h"

// 平台头文件
#include "WeakPtr.h"
#include "ElementUtils.h"
#include "UniIdentity.h"
#include "IElementParentReporter.h"
#include "ElementId.h"
#include "IGenericElement.h"
#include "DbObjectUtils.h"
#include "IBuilding.h"
#include "IDocument.h"
#include "IElementDeletionComponent.h"
#include "IElementStatus.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"



using namespace gcmp;

#pragma region 基本属性
DBOBJECT_DATA_DEFINE(LevelNameManager)
{
    m_pOwnerElement = nullptr;
}

IDocument* gcmp::LevelNameManager::GetDocument() const
{
    if (!m_pOwnerElement)
    {
        return nullptr;
    }
    return m_pOwnerElement->GetDocument();
}

gcmp::NdbObject* gcmp::LevelNameManager::GetTopOwnerObject() const
{
    return quick_cast<NdbObject>(const_cast<IElement*>(GetOwnerElement()));
}

#pragma endregion 基本属性

#pragma region 关联更新

void gcmp::LevelNameManager::UpdateForWeakParentDeletion(const std::set<ElementId>& deletedElementIds)
{
    //分区信息
    IElement* pElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"IElement为空",L"GDMPLab",L"2024-03-30");

    FOR_EACH(deletedElementId, deletedElementIds)
    {
        IElement* pElement = GetDocument()->GetElement(deletedElementId);
        if (pElement == nullptr)
        {
            continue;
        }

        IGenericElement *pBuildingElement = quick_cast<IGenericElement>(pElement);
        if (pBuildingElement == nullptr)
        {
            continue;
        }

        IBuilding* pBuiling = quick_cast<IBuilding>(pBuildingElement->GetExternalObject());
        if (pBuiling == nullptr)
        {
            continue;
        }

        if (m_Prefix.find(deletedElementId) != m_Prefix.end())
        {
            m_Prefix.erase(deletedElementId);
        }

        if (m_Suffix.find(deletedElementId) != m_Suffix.end())
        {
            m_Suffix.erase(deletedElementId);
        }

        if (m_Number.find(deletedElementId) != m_Number.end())
        {
            m_Number.erase(deletedElementId);
        }
    }
}

void gcmp::LevelNameManager::ReportParents(IElementParentReporter& reporter) const
{
    const IElement* pElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"IElement为空",L"GDMPLab",L"2024-03-30");

    FOR_EACH(iter, m_Prefix)
    {
        reporter.ReportWeak(iter.first);
    }
    FOR_EACH(iter, m_Suffix)
    {
        reporter.ReportWeak(iter.first);
    }
    FOR_EACH(iter, m_Number)
    {
        reporter.ReportWeak(iter.first);
    }
}

#pragma endregion 关联更新

#pragma region 其他
bool gcmp::LevelNameManager::FinishEditing()
{
    return true;
}
#pragma endregion 其他

#pragma region protected

bool LevelNameManager::SetOwnerElement(IElement* pOwnerElement)
{
    m_pOwnerElement = pOwnerElement;
    return true;
}

#pragma endregion protected

const LevelNameManager *gcmp::LevelNameManager::Get(const IDocument *pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空。",L"GDMPLab",L"2024-03-30");

    const IElement *pUniqueElem = pDoc->GetUniqueElementByClassUid(LevelNameManager::GetClassId().GetGuid());
    if (!pUniqueElem)
    {
        return nullptr;
    }

    const IGenericElement * pLevelNameManagerElem = quick_cast<IGenericElement>(pUniqueElem);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pLevelNameManagerElem, L"pLevelNameManagerElem为空。",L"GDMPLab",L"2024-03-30");
    const LevelNameManager * pLevelNameManager = quick_cast<LevelNameManager>(pLevelNameManagerElem->GetExternalObject());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pLevelNameManager, L"pLevelNameManager为空。",L"GDMPLab",L"2024-03-30");

    return pLevelNameManager;
}

LevelNameManager *gcmp::LevelNameManager::Get(IDocument *pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空。",L"GDMPLab",L"2024-03-30");

    IElement *pUniqueElem = pDoc->GetUniqueElementByClassUid(LevelNameManager::GetClassId().GetGuid());
    if (!pUniqueElem)
    {
        return nullptr;
    }

    IGenericElement * pLevelNameManagerElem = quick_cast<IGenericElement>(pUniqueElem);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pLevelNameManagerElem, L"pLevelNameManagerElem为空。",L"GDMPLab",L"2024-03-30");
    LevelNameManager * pLevelNameManager = quick_cast<LevelNameManager>(pLevelNameManagerElem->GetExternalObject());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pLevelNameManager, L"pLevelNameManager为空。",L"GDMPLab",L"2024-03-30");

    return pLevelNameManager;
}

LevelNameManager *gcmp::LevelNameManager::Create(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空。",L"GDMPLab",L"2024-03-30");
    LevelNameManager* pLevelNameManager = LevelNameManager::Get(pDoc);
    if (pLevelNameManager)
    {
        return pLevelNameManager;
    }

    OwnerPtr<LevelNameManager> opLevelNameManager = NEW_AS_OWNER_PTR(LevelNameManager);

    IGenericElement* pLevelNameManagerElem = IGenericElement::Create(
        pDoc, 
        TransferOwnership(opLevelNameManager), 
        LevelNameManager::GetClassId().GetGuid(), 
        ElementCreationOptions::Normal
    );

    pLevelNameManagerElem->GetStatus()->SetIsVisible(false);
    ElementUtils::MakeElementUnique(pLevelNameManagerElem, LevelNameManager::GetClassId().GetGuid());

    return quick_cast<LevelNameManager>(pLevelNameManagerElem->GetExternalObject());
}

std::wstring gcmp::LevelNameManager::GetPrefix(const ElementId &buildingId) const
{
    std::wstring defaultLevelPrefix = buildingId.IsValid() ? GBMP_TR(L"楼层 ") : GBMP_TR(L"参照标高 ");
    auto iter = GetPrefix__().find(buildingId);
    if (iter != GetPrefix__().end())
    {
        return iter->second;
    }
    return defaultLevelPrefix;
}

void gcmp::LevelNameManager::SetPrefix(const ElementId &buildingId, const std::wstring &prefix)
{
    GetPrefixFW__()[buildingId] = prefix;
}

std::wstring gcmp::LevelNameManager::GetSuffix(const ElementId &buildingId) const
{
    std::wstring defaultLevelSuffix = GBMP_TR(L"");
    auto iter = GetSuffix__().find(buildingId);
    if (iter != GetSuffix__().end())
    {
        return iter->second;
    }
    return defaultLevelSuffix;
}

void gcmp::LevelNameManager::SetSuffix(const ElementId &buildingId, const std::wstring &suffix)
{
    GetSuffixFW__()[buildingId] = suffix;
}

int gcmp::LevelNameManager::GetNumber(const ElementId &buildingId) const
{
    int defaultLevelNumber = 0;
    auto iter = GetNumber__().find(buildingId);
    if (iter != GetNumber__().end())
    {
        return iter->second;
    }
    return defaultLevelNumber;
}

void gcmp::LevelNameManager::SetNumber(const ElementId &buildingId, int number)
{
    GetNumberFW__()[buildingId] = number;
}

int gcmp::LevelNameManager::GetNextNumber(const ElementId &buildingId) const
{
    int currentNumber = GetNumber(buildingId);
    if (currentNumber >= 0)
    {
        ++currentNumber;
    }
    else
    {
        --currentNumber;
    }
    return currentNumber;
}
